import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder
import warnings
import os

warnings.filterwarnings("ignore")
pd.set_option('mode.chained_assignment', None)
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = False

data = pd.read_csv(
    os.getcwd() + "\\data\\Monroe_County_Single_Family_Residential__Building_Assets_and_Energy_Consumption__2017-2019.csv")
data.drop(
    columns=['Ethnic group', 'NYSERDA Energy Efficiency Program Participation', 'Average annual electric use (MMBtu)',
             'Average annual gas use (MMBtu)', 'Average annual total energy use (MMBtu)'], inplace=True)
print("查看数据集")
print(data.shape)

print("查看缺失值情况")
print(data.describe(include = 'all'))

plt.figure(figsize=(9, 5))

sns.distplot(data["Average annual electric use (kWh)"])
plt.xlim(0, 40000)
plt.show()

dataset = data.pivot_table(index='Median income range', columns='Number of occupants',
                           values='Average annual electric use (kWh)', aggfunc='mean')
plt.figure(figsize=(9, 5))
sns.heatmap(dataset)
plt.show()

plt.figure(figsize=(15, 6))
ax1 = plt.subplot(1, 3, 1)
plt.title("bathrooms")
sns.barplot(x="Total number of bathrooms", y="Average annual electric use (kWh)", hue="Total number of bathrooms",
            data=data, log=True)
ax2 = plt.subplot(1, 3, 2)
plt.title("kitchens")
sns.barplot(x="Number of kitchens", y="Average annual electric use (kWh)", hue="Number of kitchens", data=data,
            log=True)
ax3 = plt.subplot(1, 3, 3)
plt.title("fireplaces")
sns.barplot(x="Number of fireplaces", y="Average annual electric use (kWh)", hue="Number of fireplaces", data=data,
            log=True)
plt.subplots_adjust(wspace=0.5, hspace=15)
plt.show()

categorical_cols = ['Square footage range', 'Number of bedrooms', 'Total number of bathrooms', 'Number of kitchens',
                    'Number of fireplaces', 'Number of occupants', 'Median income range']
numeric_cols = list(set(data.columns) - set(categorical_cols))

ohe = OneHotEncoder(drop='first', sparse=False)
data = np.hstack((ohe.fit_transform(data[categorical_cols]), data[numeric_cols]))
cols = sum([(categorical_cols[i] + '_' + ohe.categories_[i][1:]).tolist() for i in range(len(categorical_cols))],
           []) + numeric_cols
data = pd.DataFrame(data, columns=cols)

id = list(data.index)
data['id'] = id
data.to_csv(os.getcwd() + "\\data\\data_power_consumption.csv")

from sklearn.cluster import KMeans


class EnergyFingerPrints():

    def __init__(self, data):
        # 统计每个聚类簇的中心点
        self.means = []
        self.data = data

    def elbow_method(self, n_clusters):
        fig, ax = plt.subplots(figsize=(8, 4))
        distortions = []

        for i in range(1, n_clusters):
            km = KMeans(n_clusters=i,
                        init='k-means++',  # 初始中心簇的获取方式，k-means++一种比较快的收敛的方法
                        n_init=10,  # 初始中心簇的迭代次数
                        max_iter=300,  # 数据分类的迭代次数
                        random_state=0)  # 初始化中心簇的方式
            km.fit(self.data)
            distortions.append(km.inertia_)  # inertia计算样本点到最近的中心点的距离之和

        plt.plot(range(1, n_clusters), distortions, marker='o', lw=1)
        plt.xlabel('聚类数量')
        plt.ylabel('至中心点距离之和')
        plt.show()

    def get_cluster_counts(self):  # 统计聚类簇和每个簇中样本的数量
        return pd.Series(self.predictions).value_counts()

    def get_cluster(self):
        return pd.DataFrame(self.predictions)

    def labels(self, n_clusters):  # 确定每簇中样本的具体划分
        self.n_clusters = n_clusters
        return KMeans(self.n_clusters, init='k-means++', n_init=10, max_iter=300, random_state=0).fit(self.data).labels_

    def fit(self, n_clusters):  # 基于划分簇的数量，对数据进行聚类分析
        self.n_clusters = n_clusters
        self.kmeans = KMeans(self.n_clusters)
        self.predictions = self.kmeans.fit_predict(self.data)


dataset = pd.read_csv(os.getcwd() + "\\data\\data_power_consumption.csv")
data = dataset[['Square footage range_<= 1,500', 'Square footage range_>=2500', 'Median income range_$50k - $100k',
                'Median income range_< $50k', 'Median income range_> $150k', 'Average annual electric use (kWh)',
                'Number of occupants_Less than 3', 'Number of occupants_More than 4']]
data = np.array(data)
energy_clusters = EnergyFingerPrints(data)
energy_clusters.elbow_method(n_clusters=13)
energy_clusters.fit(n_clusters=4)

count = energy_clusters.get_cluster_counts()
print("统计各个簇的数量")
print(count)

group = energy_clusters.labels(n_clusters=4)
data2 = pd.read_csv(os.getcwd() + "\\data\\data_power_consumption.csv")
num = data2['id']
cls = pd.DataFrame(list(num))
cls['cluster'] = list(group)
cls.columns = ['id', 'cluster']
cls = cls.sort_values(by='cluster', ascending=True)
cls.reset_index(drop=True)

print("# 第一类:")
print(np.array(cls.loc[cls.cluster == 0].id))
print("# 第二类:")
print(np.array(cls.loc[cls.cluster == 1].id))
print("# 第三类:")
print(np.array(cls.loc[cls.cluster == 2].id))
print("# 第四类:")
print(np.array(cls.loc[cls.cluster == 3].id))

cls = energy_clusters.get_cluster()
cls_data = pd.DataFrame(data)
cls_data = pd.merge(cls_data, cls, left_index=True, right_index=True)
cls_data = cls_data.reset_index()
color = ["red", "pink", "orange", "gray"]
plt.figure(figsize=(15, 10))
for i in range(4):
    plt.scatter(cls_data.loc[cls_data['0_y'] == i, 'index'], cls_data.loc[cls_data['0_y'] == i, 5]
                # 就是取出y_pred是0，1，2，3的那一簇的X
                , marker='o'  # 点的形状
                , s=8  # 点的大小
                , c=color[i]
                )
plt.show()

plt.figure(figsize=(15, 10))
sns.lineplot(x=cls_data.index, y=5, hue='0_y', data=cls_data)
plt.ylabel('年均用电量')
plt.show()

dataset = pd.read_csv(os.getcwd() + "\\data\\data_power_consumption.csv")
data = dataset[['Number of bedrooms_3', 'Number of bedrooms_4 or more', 'Total number of bathrooms_2 or 2.5',
                'Total number of bathrooms_3 or more', 'Number of kitchens_2 or more',
                'Average annual electric use (kWh)', 'Number of fireplaces_1 or more']]
data = np.array(data)
energy_clusters = EnergyFingerPrints(data)
energy_clusters.elbow_method(n_clusters=13)
energy_clusters.fit(n_clusters=4)

count = energy_clusters.get_cluster_counts()
print("统计各个簇的数量:")
print(count)

group = energy_clusters.labels(n_clusters=4)
data2 = pd.read_csv(os.getcwd() + "\\data\\data_power_consumption.csv")
num = data2['id']
cls = pd.DataFrame(list(num))
cls['cluster'] = list(group)
cls.columns = ['id', 'cluster']
cls = cls.sort_values(by='cluster', ascending=True)
cls.reset_index(drop=True)

print("# 第一类:")
print(np.array(cls.loc[cls.cluster == 0].id))
print("# 第二类:")
print(np.array(cls.loc[cls.cluster == 1].id))
print("# 第三类:")
print(np.array(cls.loc[cls.cluster == 2].id))
print("# 第四类:")
print(np.array(cls.loc[cls.cluster == 3].id))

cls = energy_clusters.get_cluster()
cls_data = pd.DataFrame(data)
cls_data = pd.merge(cls_data, cls, left_index=True, right_index=True)
cls_data = cls_data.reset_index()
color = ["red", "pink", "orange", "gray"]
plt.figure(figsize=(15, 10))
for i in range(4):
    plt.scatter(cls_data.loc[cls_data['0_y'] == i, 'index'], cls_data.loc[cls_data['0_y'] == i, 5]
                # 就是取出y_pred是0，1，2，3的那一簇的X
                , marker='o'  # 点的形状
                , s=8  # 点的大小
                , c=color[i]
                )
plt.show()

plt.figure(figsize=(15, 10))
sns.lineplot(x=cls_data.index, y=5, hue='0_y', data=cls_data)
plt.ylabel('年均用电量')
plt.show()
